/*
 * @(#)RegistryWebService.java
 * Date 2013-04-03
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.ws;

import javax.annotation.Resource;

import javax.inject.Inject;

import javax.jws.HandlerChain;
import javax.jws.WebService;

import javax.xml.ws.BindingType;
import javax.xml.ws.WebServiceContext;

import javax.xml.ws.soap.Addressing;
import javax.xml.ws.soap.SOAPBinding;

import ihe.iti.xds_b._2007.DocumentRegistryPortType;

import oasis.names.tc.ebxml_regrep.xsd.lcm._3.SubmitObjectsRequest;

import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryRequest;
import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryResponse;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.RegistryObjectListType;

import oasis.names.tc.ebxml_regrep.xsd.rs._3.RegistryResponseType;

import org.hl7.v3.MCCIIN000002UV01;
import org.hl7.v3.PRPAIN201301UV02;
import org.hl7.v3.PRPAIN201302UV02;
import org.hl7.v3.PRPAIN201304UV02;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.hornerscorners.lamppost.atna.client.utils.AtnaUtils;

import us.hornerscorners.lamppost.config.IServiceConfig;

import us.hornerscorners.lamppost.exception.ServiceActionError;
import us.hornerscorners.lamppost.exception.SeverityType;

import us.hornerscorners.lamppost.ihecommon.config.IHEConfig;
import us.hornerscorners.lamppost.ihecommon.config.IHEServiceType;

import us.hornerscorners.lamppost.model.audit.AuditContext;
import us.hornerscorners.lamppost.model.audit.CodedValueType;

import us.hornerscorners.lamppost.registry.constant.ErrorCode;
import us.hornerscorners.lamppost.registry.constant.ResponseStatus;

import us.hornerscorners.lamppost.registry.inject.RegistryTarget;

import us.hornerscorners.lamppost.registry.model.RegistryResponse;

import us.hornerscorners.lamppost.registry.service.IPatientIdentityService;
import us.hornerscorners.lamppost.registry.service.IRegistryPersistService;
import us.hornerscorners.lamppost.registry.service.IRegistryQueryService;

import us.hornerscorners.lamppost.registry.transformer.xds
    .RegistryResponseTypeTransformer;

import us.hornerscorners.lamppost.ws.SOAPContextParser;


/**
 * Class description
 *
 *
 * @version v1.0, 2013-04-03
 * @author Jim Horner
 */
@WebService(
    portName = "DocumentRegistry_Port_Soap12",
    serviceName = "DocumentRegistry_Service",
    targetNamespace = "urn:ihe:iti:xds-b:2007",
    endpointInterface = "ihe.iti.xds_b._2007.DocumentRegistryPortType",
    wsdlLocation = "WEB-INF/wsdl/registry/XDS.b_DocumentRegistry.wsdl"
)
@HandlerChain(file = "META-INF/registry-handler-chain.xml")
@Addressing(enabled = true, required = true)
@BindingType(SOAPBinding.SOAP12HTTP_BINDING)
public class RegistryWebService implements DocumentRegistryPortType {

    /** Field description */
    @Inject
    private IHEConfig config;

    /** Field description */
    @Resource
    private WebServiceContext context;

    /** Field description */
    @Inject
    private SOAPContextParser contextParser;

    /** Field description */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /** Field description */
    @Inject
    private IPatientIdentityService patientIdentityService;

    /** Field description */
    @Inject
    private IRegistryQueryService registryQueryService;

    /** Field description */
    @Inject
    private IRegistryPersistService registryRegisterService;

    /** Field description */
    @Inject
    @RegistryTarget
    private RegistryResponseTypeTransformer responseTypeTransformer;

    /**
     * Method description
     *
     *
     * @param body
     *
     * @return
     */
    @Override
    public MCCIIN000002UV01 documentRegistryPRPAIN201301UV02(PRPAIN201301UV02 body) {

        MCCIIN000002UV01 result = null;

        // PIX Add Patient
        try {

            result = this.patientIdentityService.addPatientIdentity(body);

        } catch (Exception e) {

            // create a response
            logger.error(e.getMessage(), e);

            // TODO fix this
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param body
     *
     * @return
     */
    @Override
    public MCCIIN000002UV01 documentRegistryPRPAIN201302UV02(PRPAIN201302UV02 body) {

        MCCIIN000002UV01 result = null;

        // PIX Patient Revised
        try {

            result = this.patientIdentityService.revisePatientIdenity(body);

        } catch (Exception e) {

            // create a response
            logger.error(e.getMessage(), e);

            // TODO fix this
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param body
     *
     * @return
     */
    @Override
    public MCCIIN000002UV01 documentRegistryPRPAIN201304UV02(PRPAIN201304UV02 body) {

        MCCIIN000002UV01 result = null;

        // PIX Patient Duplicates Resolved
        try {

            result = this.patientIdentityService.resolvePatientIdentity(body);

        } catch (Exception e) {

            // create a response
            logger.error(e.getMessage(), e);

            // TODO fix this
        }

        return result;
    }

    /**
     * ITI-42 Register Document Set-b
     *
     *
     * @param body
     *
     * @return
     */
    @Override
    public RegistryResponseType documentRegistryRegisterDocumentSetB(
            SubmitObjectsRequest body) {

        RegistryResponseType result = null;

        // register documents
        try {
            
            logger.debug("XDS Registry - Register Document Set.b started");
            
            CodedValueType eventType = AtnaUtils.createCodedValue("ITI-42",
                                           "IHE Transactions", "Register Document Set-b");

            IServiceConfig serviceConfig =
                this.config.findServiceConfig(IHEServiceType.Registry);

            AuditContext auditContext =
                this.contextParser.parseAuditContext(this.context, eventType,
                    serviceConfig);

            result = this.registryRegisterService.registerDocumentSet(auditContext, body);

        } catch (Exception e) {

            // create a response
            logger.error(e.getMessage(), e);

            ServiceActionError error =
                new ServiceActionError(ErrorCode.XDSRegistryError.getCode(),
                                       e.getMessage(), SeverityType.Error);

            RegistryResponse response = new RegistryResponse(ResponseStatus.Failure,
                                            getClass(), error);

            result = this.responseTypeTransformer.transform(response);
        }

        return result;
    }

    /**
     * ITI-18 Registry Stored Query
     *
     *
     * @param body
     *
     * @return
     */
    @Override
    public AdhocQueryResponse documentRegistryRegistryStoredQuery(
            AdhocQueryRequest body) {

        AdhocQueryResponse result = null;

        try {

            logger.debug("XDS Registry - Stored Query started");
            
            CodedValueType eventType = AtnaUtils.createCodedValue("ITI-18",
                                           "IHE Transactions", "Registry Stored Query");

            IServiceConfig serviceConfig =
                this.config.findServiceConfig(IHEServiceType.Registry);

            AuditContext auditContext =
                this.contextParser.parseAuditContext(this.context, eventType,
                    serviceConfig);

            result = this.registryQueryService.executeStoredQuery(auditContext, body);

        } catch (Exception e) {

            // create a response
            logger.error(e.getMessage(), e);

            ServiceActionError error =
                new ServiceActionError(ErrorCode.XDSRegistryError.getCode(),
                                       e.getMessage(), SeverityType.Error);

            result = new AdhocQueryResponse();
            result.setRegistryObjectList(new RegistryObjectListType());
            result.setStatus(ResponseStatus.Failure.getCode());
            result.setRegistryErrorList(
                this.responseTypeTransformer.createRegistryErrorList(getClass(), error));
        }

        return result;
    }
}
